/*
SteelNzb
Copyright (C) 2008  Wessel v. Staal

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "global.h"
#include "ydec.h"
#include "crc.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>



#ifdef WIN32
#include <windows.h>
#ifndef WINCE
#include <direct.h>
#endif
#define stricmp _stricmp
#define unlink _unlink
#else
#include <unistd.h>
#include <dirent.h>
#define stricmp strcasecmp
#endif

int ydec_decodeCollection(char* mainSourceFilename, char* destPath, int collectionCount)
{
	unsigned char line[4000];
	unsigned char output[2048];
	char* cr = NULL;
	unsigned char* inputc = NULL;
	unsigned char c = 0;
	long  size = 0;
	long  begin = 0;
	long  end = 0;
	char filename[255];
	char path[1024];
	char* substr = NULL;
	int partc = 0;
	int ispart = 0;
	long  processed = 0;
	FILE* fpout = NULL;
	FILE* fpin = NULL;
	int outlength = 0;
	int partn = 1;
	char* quote1 = NULL, *quote2 = NULL;
	int i = 0;
	DWORD crcval = 0xFFFFFFFF;
	int wasYEnc = 0;

	memset(line, 0, sizeof(line));
	
	for ( i=1;i<=collectionCount; i++ )
	{
		sprintf(path, "%s.%i", mainSourceFilename, i);

		if ( (fpin = fopen(path, "rb")) == NULL )
		{
			fprintf(stderr, "DecodeYEnc::Could not open %s, part %i\n", mainSourceFilename, i);
			if ( fpout != NULL ) fclose(fpout);

			return 0;
		}

		while ( fgets((char*) line, sizeof(line), fpin) != NULL )
		{
			if ( (cr = strchr((char*) line, '\r')) != NULL )
				*cr = 0;

			if ( memcmp(line, "=ybegin", 7) == 0 )
			{
				if ( (substr = strstr((char*) line, "size=")) == NULL )
				{
					fprintf(stderr, "DecodeYEnc::No size attribute found %s, part %i\n", mainSourceFilename, i);
					
					if ( fpin != NULL ) fclose(fpin);
					if ( fpout != NULL ) fclose(fpout);

					return 0;
				}

				processed = 0;
				size = atol(substr+5);
				
				if ( (substr = strstr((char*) line, "name=")) == NULL )
				{
					fprintf(stderr, "DecodeYEnc::No name attribute found %s, part %i\n", mainSourceFilename, i);

					if ( fpin != NULL ) fclose(fpin);
					if ( fpout != NULL ) fclose(fpout);

					return 0;
				}

				if ( (quote1 = strchr((char*) substr+5, '"')) != NULL )
				{
					if ( (quote2 = strchr((char*) quote1+1, '"')) != NULL )
					{
						memcpy(filename, quote1+1, quote2-quote1-1);
					}
				}
				else
					strcpy(filename, substr+5);
				
				sprintf(path, "%s/%s", destPath, filename);

				if ( (substr = strstr((char*) line, "part=")) != NULL )
				{
					ispart = 1;
					partc = atoi(substr+5);

					if ( atoi(substr+5) != partn )
					{
						fprintf(stderr, "DecodeYEnc::Part sequence does not match %s, part %i\n", mainSourceFilename, i);
						
						if ( fpin != NULL ) fclose(fpin);
						if ( fpout != NULL ) fclose(fpout);

						return 0;
					}
				}

				if ( !ispart || partn == 1 )
					fpout = fopen(path, "wb+");
				else
					fpout = fopen(path, "ab");

				if ( fpout == NULL )
				{
					fprintf(stderr, "DecodeYEnc::Cannot create output file %s, part %i\n", mainSourceFilename, i);

					if ( fpin != NULL ) fclose(fpin);
					if ( fpout != NULL ) fclose(fpout);

					return 0;
				}

				wasYEnc = 1;
				crcval = 0xFFFFFFFF;
			}
			else if ( ispart && memcmp(line, "=ypart", 6) == 0 )
			{
				if ( (substr = strstr((char*) line, "begin=")) == NULL )
				{
					fprintf(stderr, "DecodeYEnc::No begin attribute found %s, part %i\n", mainSourceFilename, i);
					
					if ( fpin != NULL ) fclose(fpin);
					if ( fpout != NULL ) fclose(fpout);

					return 0;
				}

				begin = atol(substr+6);

				if ( (substr = strstr((char*) line, "end=")) == NULL )
				{
					fprintf(stderr, "DecodeYEnc::No end attribute found %s, part %i\n", mainSourceFilename, i);

					if ( fpin != NULL ) fclose(fpin);
					if ( fpout != NULL ) fclose(fpout);

					return 0;
				}

				end = atol(substr+4);

				crcval = 0xFFFFFFFF;
			}
			else if ( memcmp(line, "=yend", 5) == 0 )
			{
				if ( processed-1 != end-begin )
				{
					fprintf(stderr, "DecodeYEnc::Size does not match size processed %s, part %i\n", mainSourceFilename, i);

					if ( fpin != NULL ) fclose(fpin);
					if ( fpout != NULL ) fclose(fpout);
				}
				
				if ( (substr = strstr((char*) line, "pcrc32=")) != NULL )
				{
					char computedCrc[12];
					char* readCrc = NULL;

					sprintf(computedCrc, "%08lx", ~crcval);

					readCrc = ((char*)line+(substr-(char*)line))+7;

					if ( memcmp(computedCrc, readCrc, 6) != 0 )
					{
						fprintf(stderr, "DecodeYEnc::Crc mismatch in file %s, part %i\n", mainSourceFilename, i);

						if ( fpin != NULL ) fclose(fpin);
						if ( fpout != NULL ) fclose(fpout);

						return 0;
					}
				}

				if ( outlength > 0 )
				{
					fwrite(output, outlength, 1, fpout);
					outlength = 0;
				}

				partn++;

				fclose(fpout);
				fpout = NULL;
			}
			else if ( fpout != NULL )
			{
				inputc = (unsigned char*)&line;

				while ( (c = *(inputc++)) != 0 )
				{
					if ( c == '=' )
					{
						c = *(inputc++);
						c-=64;
					}

					c -= 42;


					crcval = updateCRC32(c, crcval);
					output[outlength++] = c;
					processed++;

					if ( outlength == sizeof(output) )
					{
						fwrite(output, outlength, 1, fpout);
						outlength = 0;
					}
				}
			}

			memset(line, 0, sizeof(line));
		}

		fclose(fpin);
	}

	if ( fpout != NULL )
		fclose(fpout);

	if ( !wasYEnc )
	{
		fprintf(stderr, "DecodeYEnc::No evidence of yEnc found in collection '%s'!", mainSourceFilename);
		return 0;
	}

	return 1;
}
